﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MarioMoveScript : MonoBehaviour {

	Animator anim;
	public float doubleTimef;
	bool bDouble;
	int keyDownCnt;
	InputKey lastKey;
	Direction curD;
	Vector3 scale;
	static float SPEED_NORMAL = 50f;
	static float SPEED_DASH = 100f;
	MoveState moveState;

	CameraScript cameraScript;

	enum Direction {
		D_Up,
		D_URight,
		D_Right,
		D_DRight,
		D_Down,
		D_DLeft,
		D_Left,
		D_ULeft,

		D_None,
		D_Count
	};

	enum MoveState { 
		Move_Idle,
		Move_Walk,
		Move_Dash,

		Move_Count
	};

	enum InputType {
		InputType_Down,
		InputType_Hold,
		InputType_Up
	};

	enum InputKey {
		Input_Up,
		Input_Down,
		Input_Left,
		Input_Right,

		Input_None
	};

	string[,] marioMoveAnimStr = new string[,] {
		{ "NMWalk_N", 	"NMWalk_N", 	"NMWalk_N" },
		{ "NMWalk_NE", 	"NMWalk_NE",	"NMWalk_NE" },
		{ "NMWalk_E", 	"NMWalk_E", 	"NMWalk_E" },
		{ "NMWalk_SE", 	"NMWalk_SE", 	"NMWalk_SE" },
		{ "NMWalk_S", 	"NMWalk_S", 	"NMWalk_S" },
		{ "NMWalk_SE", 	"NMWalk_SE", 	"NMWalk_SE" },
		{ "NMWalk_E", 	"NMWalk_E", 	"NMWalk_E" },
		{ "NMWalk_NE",	"NMWalk_NE", 	"NMWalk_NE" }
//		{ "MIdle_SW", 	"MWalk_SW", 	"MDash_SW" },
//		{ "MIdle_W", 	"MWalk_W", 		"MDash_W" },
//		{ "MIdle_NW",	"MWalk_NW", 	"MDash_NW" }
	};

//	string[,] marioMoveAnimStr = new string[,] {
//		{ "MIdle_N", 	"NMWalk_N", 	"MDash_N" },
//		{ "MIdle_NE", 	"NMWalk_NE",	"MDash_NE" },
//		{ "MIdle_E", 	"NMWalk_E", 	"MDash_E" },
//		{ "MIdle_SE", 	"NMWalk_SE", 	"MDash_SE" },
//		{ "MIdle_S", 	"NMWalk_S", 	"MDash_S" },
//		{ "MIdle_SW", 	"NMWalk_SE", 	"MDash_SW" },
//		{ "MIdle_W", 	"NMWalk_E", 	"MDash_W" },
//		{ "MIdle_NW",	"NMWalk_NE", 	"MDash_NW" }
//		//		{ "MIdle_SW", 	"MWalk_SW", 	"MDash_SW" },
//		//		{ "MIdle_W", 	"MWalk_W", 		"MDash_W" },
//		//		{ "MIdle_NW",	"MWalk_NW", 	"MDash_NW" }
//	};
	void Start()
	{
		anim = GetComponent<Animator>();
		bDouble = false;
		keyDownCnt = 0;
		lastKey = InputKey.Input_None;
		curD = Direction.D_None;
		scale = new Vector3(1,1,1);
		moveState = MoveState.Move_Idle;

		GameObject gc = GameObject.Find("Main Camera");
		cameraScript = gc.GetComponent<CameraScript>();
	}

	// Update is called once per frame
	void Update () {
		if(cameraScript.bMoving)
			return;

		Direction d = Direction.D_None;
		Vector2 vec = new Vector2(0,0);

		if(!bDouble && lastKey != InputKey.Input_None)
		{
			if(doubleTimef > 0.0f && (IsInput(InputType.InputType_Down, lastKey)))
			{
				bDouble = true;
			}
			doubleTimef -= Time.fixedDeltaTime*10;
			if(doubleTimef < 0)
				doubleTimef = 0;
		}

		if(IsInput(InputType.InputType_Down, InputKey.Input_Up)){
			keyDownCnt ++;
			lastKey = InputKey.Input_Left;
		} else if (IsInput(InputType.InputType_Down, InputKey.Input_Down)) {
			keyDownCnt ++;
			lastKey = InputKey.Input_Down;
		} else if (IsInput(InputType.InputType_Down, InputKey.Input_Left)) {
			keyDownCnt ++;
			lastKey = InputKey.Input_Left;
		} else if (IsInput(InputType.InputType_Down, InputKey.Input_Right)) {
			keyDownCnt ++;
			lastKey = InputKey.Input_Right;
		}

		// Check Input
		if(IsInput(InputType.InputType_Hold, InputKey.Input_Up))
			d = Direction.D_Up;
//		if(Input.GetKey(KeyCode.S))
		if(IsInput(InputType.InputType_Hold, InputKey.Input_Down))
			d = Direction.D_Down;
		if(IsInput(InputType.InputType_Hold, InputKey.Input_Left))
		{
			switch(d) {
			case Direction.D_Up:	d = Direction.D_ULeft;	break;
			case Direction.D_Down:	d = Direction.D_DLeft;	break;
			case Direction.D_None:	d = Direction.D_Left;	break;
			}
		}
		if(IsInput(InputType.InputType_Hold, InputKey.Input_Right))
		{
			switch(d) {
			case Direction.D_Up:	d = Direction.D_URight;	break;
			case Direction.D_Down:	d = Direction.D_DRight;	break;
			case Direction.D_None:	d = Direction.D_Right;	break;
			}
		}

		// Play Animation
		if(d != Direction.D_None) {
			curD = d;

			switch(d) {
			case Direction.D_DLeft:
			case Direction.D_Left:
			case Direction.D_ULeft:
				scale.x = -1;
				break;
			default:
				scale.x = 1;
				break;
			}
			anim.enabled = true;
			anim.speed = (bDouble) ? 2.0f : 1.0f;
			anim.Play(marioMoveAnimStr[(int)d,(bDouble) ? (int)MoveState.Move_Dash : (int)MoveState.Move_Walk]);
		}

		// Check Direction, Set Anim
		switch(d) {
		case Direction.D_Up:
			if(bDouble) {
				vec.y = SPEED_DASH;
			} else {
				vec.y = SPEED_NORMAL;
			}
			break;
		case Direction.D_Down:
			if(bDouble) {
				vec.y = -SPEED_DASH;
			} else {
				vec.y = -SPEED_NORMAL;
			}
			break;
		case Direction.D_Right:
			if(bDouble) {
				vec.x = SPEED_DASH;
			} else {
				vec.x = SPEED_NORMAL;
			}
			break;
		case Direction.D_URight:
			if(bDouble) {
				vec.x = SPEED_DASH;
				vec.y = SPEED_DASH;
			} else {
				vec.x = SPEED_NORMAL;
				vec.y = SPEED_NORMAL;
			}
			break;
		case Direction.D_DRight:
			if(bDouble) {
				vec.x = SPEED_DASH;
				vec.y = -SPEED_DASH;
			} else {
				vec.x = SPEED_NORMAL;
				vec.y = -SPEED_NORMAL;
			}
			break;
		case Direction.D_Left:
			if(bDouble) {
				vec.x = -SPEED_DASH;
			} else {
				vec.x = -SPEED_NORMAL;
			}
			break;
		case Direction.D_ULeft:
			if(bDouble) {
				vec.x = -SPEED_DASH;
				vec.y = SPEED_DASH;
			} else {
				vec.x = -SPEED_NORMAL;
				vec.y = SPEED_NORMAL;
			}
			break;
		case Direction.D_DLeft:
			if(bDouble) {
				vec.x = -SPEED_DASH;
				vec.y = -SPEED_DASH;
			} else {
				vec.x = -SPEED_NORMAL;
				vec.y = -SPEED_NORMAL;
			}
			break;
		}

		// KeyUp Check
//		if(Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D))
		if(IsInput(InputType.InputType_Up, InputKey.Input_Down) || IsInput(InputType.InputType_Up, InputKey.Input_Up) ||
		   IsInput(InputType.InputType_Up, InputKey.Input_Left) || IsInput(InputType.InputType_Up, InputKey.Input_Right)) {
			if(keyDownCnt-1 < 0)
				keyDownCnt = 0;
			else
				keyDownCnt --;
		}
		if(keyDownCnt == 0)
		{
			if(bDouble) {
				bDouble = false;
				lastKey = InputKey.Input_None;
				
//				Debug.Log("Double Check Reset");
			}
			doubleTimef = 2f;

			// Change Animation By Velocity
			if(curD != Direction.D_None)
			{
				if((Mathf.Abs(rigidbody2D.velocity.x) > 0.3 && Mathf.Abs(rigidbody2D.velocity.x) <= 0.6f ||
				   Mathf.Abs(rigidbody2D.velocity.y) > 0.3 && Mathf.Abs(rigidbody2D.velocity.y) <= 0.6f) &&
				   moveState != MoveState.Move_Walk)
				{
					anim.enabled = true;
					anim.speed = 1.0f;
					anim.Play (marioMoveAnimStr[(int)curD, (int)MoveState.Move_Walk]);
					moveState = MoveState.Move_Walk;
				}
				else if(Mathf.Abs(rigidbody2D.velocity.x) <= 0.3 && Mathf.Abs(rigidbody2D.velocity.y) <= 0.3 &&
				        moveState != MoveState.Move_Idle)
				{	
					anim.enabled = false;

					anim.speed = 1.0f;
					anim.Play (marioMoveAnimStr[(int)curD, (int)MoveState.Move_Idle]);
					curD = Direction.D_None;
					moveState = MoveState.Move_Idle;
				}
			}
		}
		if(vec.x == 0 && vec.y == 0 && rigidbody2D.velocity.x == 0 && rigidbody2D.velocity.y == 0)
			keyDownCnt = 0;

		rigidbody2D.AddForce(vec);
		transform.localScale = scale;
	}

	void OnTriggerEnter2D (Collider2D other) {
		switch(other.name) {
		case "ExitUp":
			cameraScript.MoveUP();
			break;
		case "ExitDown":
			cameraScript.MoveDown();
			break;
		}
		Debug.Log(other.name);
	}

	bool IsInput(InputType type, InputKey key)
	{
		switch (key)
		{
			case InputKey.Input_Down:
			{
				switch(type)
				{
				case InputType.InputType_Down:
					if(Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow) || Input.GetAxis("Vertical") < 0f)
						return true;
					break;
				case InputType.InputType_Hold:
					if(Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) || Input.GetAxis("Vertical") < 0f)
						return true;
					break;
				case InputType.InputType_Up:
					if(Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.DownArrow) || Input.GetAxis("Vertical") == 0f)
						return true;
					break;
				}
			}
				break;
			case InputKey.Input_Up:
			{
				switch(type)
				{
				case InputType.InputType_Down:
					if(Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow) || Input.GetAxis("Vertical") > 0f)
						return true;
					break;
				case InputType.InputType_Hold:
					if(Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow) || Input.GetAxis("Vertical") > 0f)
						return true;
					break;
				case InputType.InputType_Up:
				if(Input.GetKeyUp(KeyCode.W) || Input.GetKeyUp(KeyCode.UpArrow) || Input.GetAxis("Vertical") == 0f)
						return true;
					break;
				}
			}
				break;
			case InputKey.Input_Left:
			{
				switch(type)
				{
				case InputType.InputType_Down:
				if(Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetAxis("Horizontal") < 0f)
						return true;
					break;
				case InputType.InputType_Hold:
					if(Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) || Input.GetAxis("Horizontal") < 0f)
						return true;
					break;
				case InputType.InputType_Up:
					if(Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetAxis("Horizontal") == 0f)
						return true;
					break;
				}
			}
				break;
			case InputKey.Input_Right:
			{
				switch(type)
				{
				case InputType.InputType_Down:
					if(Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow) || Input.GetAxis("Horizontal") > 0f)
						return true;
					break;
				case InputType.InputType_Hold:
					if(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) || Input.GetAxis("Horizontal") > 0f)
						return true;
					break;
				case InputType.InputType_Up:
					if(Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.RightArrow) || Input.GetAxis("Horizontal") == 0f)
						return true;
					break;
				}
			}
				break;
		}
		return false;
	}
}
